home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / comms / non-internet / samba / source / nmbsync.c < prev    next >
C/C++ Source or Header  |  1996-06-26  |  8KB  |  300 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    NBT netbios routines to synchronise browse lists
  5.    Copyright (C) Andrew Tridgell 1994-1995
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.    
  21. */
  22.  
  23. #include "includes.h"
  24. #include "loadparm.h"
  25. #include "nameserv.h"
  26.  
  27. extern int DEBUGLEVEL;
  28.  
  29. struct server_record *add_server_entry(char *name,int servertype,
  30.                        int ttl,char *comment,BOOL replace);
  31.  
  32.  
  33. /****************************************************************************
  34. call a remote api
  35. ****************************************************************************/
  36. static BOOL call_remote_api(int fd,int cnum,int uid,int timeout,
  37.                 char *inbuf,char *outbuf,
  38.                 int prcnt,int drcnt,
  39.                 int mprcnt,int mdrcnt,
  40.                 int *rprcnt,int *rdrcnt,
  41.                 char *param,char *data,
  42.                 char **rparam,char **rdata)
  43. {
  44.   char *p1,*p2;
  45.  
  46.   /* send a SMBtrans command */
  47.   bzero(outbuf,smb_size);
  48.   set_message(outbuf,14,0,True);
  49.   CVAL(outbuf,smb_com) = SMBtrans;
  50.   SSVAL(outbuf,smb_tid,cnum);
  51.   SSVAL(outbuf,smb_uid,uid);
  52.  
  53.   p1 = smb_buf(outbuf);
  54.   strcpy(p1,"\\PIPE\\LANMAN");
  55.   p1 = skip_string(p1,1);
  56.   p2 = p1 + prcnt;
  57.  
  58.   if (prcnt > 0)
  59.     memcpy(p1,param,prcnt);
  60.   if (drcnt > 0)
  61.     memcpy(p2,data,drcnt);
  62.  
  63.   SSVAL(outbuf,smb_vwv0,prcnt); /* param count */
  64.   SSVAL(outbuf,smb_vwv1,drcnt); /* data count */
  65.   SSVAL(outbuf,smb_vwv2,mprcnt); /* mprcnt */
  66.   SSVAL(outbuf,smb_vwv3,mdrcnt); /* mdrcnt */
  67.   SSVAL(outbuf,smb_vwv4,0); /* msrcnt */
  68.   SSVAL(outbuf,smb_vwv5,0); /* flags */
  69.   SSVAL(outbuf,smb_vwv9,prcnt); /* pscnt */
  70.   SSVAL(outbuf,smb_vwv10,smb_offset(p1,outbuf)); /* psoff */
  71.   SSVAL(outbuf,smb_vwv11,drcnt); /* dscnt */
  72.   SSVAL(outbuf,smb_vwv12,smb_offset(p2,outbuf)); /* dsoff */
  73.   CVAL(outbuf,smb_vwv13) = 0; /* suwcnt */
  74.  
  75.   set_message(outbuf,14,PTR_DIFF(p2+drcnt,smb_buf(outbuf)),False);
  76.  
  77.   send_smb(fd,outbuf);
  78.   
  79.   if (receive_smb(fd,inbuf,timeout) &&
  80.       CVAL(inbuf,smb_rcls) == 0)
  81.     {
  82.       if (rparam)
  83.     *rparam = inbuf+4 + SVAL(inbuf,smb_vwv4);
  84.       if (rdata)
  85.     *rdata = inbuf+4 + SVAL(inbuf,smb_vwv7);
  86.       if (rprcnt)
  87.     *rprcnt = SVAL(inbuf,smb_vwv3);
  88.       if (rdrcnt)
  89.     *rdrcnt = SVAL(inbuf,smb_vwv6);
  90.       return(True);
  91.     }
  92.  
  93.   return(False);
  94. }
  95.  
  96.  
  97. /*******************************************************************
  98.   synchronise browse lists with another browse server
  99.   ******************************************************************/
  100. void sync_browse_lists(char *name,int name_type,char *myname,
  101.                char *domain,struct in_addr ip)
  102. {
  103.   char *protocol = "LM1.2X002";
  104.   char *service = "IPC$";
  105.   char *dev = "IPC";
  106.   int timeout=2000;
  107.   char *inbuf=NULL;
  108.   pstring outbuf;
  109.   char *p;
  110.   int len;
  111.   uint32 sesskey;
  112.   int cnum,uid;
  113.   BOOL ret;
  114.  
  115.   int fd = open_socket_out(SOCK_STREAM, &ip, SMB_PORT);
  116.   if (fd < 0) {
  117.     DEBUG(3,("Failed to connect to %s at %s\n",name,inet_ntoa(ip)));
  118.     return;
  119.   }
  120.  
  121.   if (!(inbuf = (char *)malloc(0xFFFF+1024))) return;  
  122.  
  123.   /* put in the destination name */
  124.   len = 4;
  125.   p = outbuf+len;
  126.   name_mangle(name,p,name_type);
  127.   len += name_len(p);
  128.  
  129.   /* and my name */
  130.   p = outbuf+len;
  131.   name_mangle(myname,p,0x20);
  132.   len += name_len(p);
  133.  
  134.   _smb_setlen(outbuf,len);
  135.   CVAL(outbuf,0) = 0x81;
  136.  
  137.   send_smb(fd,outbuf);
  138.   receive_smb(fd,inbuf,5000);
  139.   
  140.   bzero(outbuf,smb_size);
  141.  
  142.   /* setup the protocol string */
  143.   set_message(outbuf,0,strlen(protocol)+2,True);
  144.   p = smb_buf(outbuf);
  145.   *p++ = 2;
  146.   strcpy(p,protocol);
  147.  
  148.   CVAL(outbuf,smb_com) = SMBnegprot;
  149.   CVAL(outbuf,smb_flg) = 0x8;
  150.   SSVAL(outbuf,smb_flg2,0x1);
  151.  
  152.   send_smb(fd,outbuf);
  153.   bzero(inbuf,smb_size);
  154.   ret = receive_smb(fd,inbuf,timeout);
  155.   
  156.   if (!ret || CVAL(inbuf,smb_rcls) || SVAL(inbuf,smb_vwv0)) {
  157.     DEBUG(3,("%s rejected the protocol\n",name));
  158.     close(fd);
  159.     if (inbuf) free(inbuf);
  160.     return;
  161.   }
  162.  
  163.   sesskey = IVAL(inbuf,smb_vwv6);
  164.  
  165.   bzero(outbuf,smb_size);
  166.   set_message(outbuf,10,2,True);
  167.   CVAL(outbuf,smb_com) = SMBsesssetupX;
  168.  
  169.   CVAL(outbuf,smb_vwv0) = 0xFF;
  170.   SSVAL(outbuf,smb_vwv2,0xFFFF);
  171.   SSVAL(outbuf,smb_vwv3,2);
  172.   SSVAL(outbuf,smb_vwv4,1);
  173.   SIVAL(outbuf,smb_vwv5,sesskey);
  174.   SSVAL(outbuf,smb_vwv7,1);
  175.  
  176.   send_smb(fd,outbuf);
  177.   bzero(inbuf,smb_size);
  178.   ret = receive_smb(fd,inbuf,timeout);
  179.   if (!ret || CVAL(inbuf,smb_rcls)) {
  180.     DEBUG(3,("%s rejected session setup\n",name));
  181.     close(fd);
  182.     if (inbuf) free(inbuf);
  183.     return;
  184.   }
  185.  
  186.   uid = SVAL(inbuf,smb_uid);
  187.  
  188.   bzero(outbuf,smb_size);
  189.   set_message(outbuf,4,2 + strlen(service) + 1 + strlen(dev),True);
  190.   CVAL(outbuf,smb_com) = SMBtconX;
  191.   SSVAL(outbuf,smb_uid,uid);
  192.  
  193.   SSVAL(outbuf,smb_vwv0,0xFF);
  194.   SSVAL(outbuf,smb_vwv3,1);
  195.  
  196.   p = smb_buf(outbuf) + 1;
  197.   strcpy(p,service);
  198.   p = skip_string(p,1);
  199.   strcpy(p,dev);
  200.  
  201.   send_smb(fd,outbuf);
  202.   bzero(inbuf,smb_size);
  203.   ret = receive_smb(fd,inbuf,timeout);
  204.   if (!ret || CVAL(inbuf,smb_rcls)) {
  205.     DEBUG(3,("%s rejected IPC connect (%d,%d)\n",name,
  206.          CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err)));
  207.     close(fd);
  208.     if (inbuf) free(inbuf);
  209.     return;
  210.   }
  211.  
  212.   cnum = SVAL(inbuf,smb_tid);
  213.   
  214.   /* now I need to send a NetServerEnum */
  215.   {
  216.     fstring param;
  217.     uint32 *typep;
  218.     char *rparam,*rdata;
  219.  
  220.     p = param;
  221.     SSVAL(p,0,0x68); /* api number */
  222.     p += 2;
  223.     strcpy(p,"WrLehDz");
  224.     p = skip_string(p,1);
  225.  
  226.     strcpy(p,"B16BBDz");
  227.  
  228.     p = skip_string(p,1);
  229.     SSVAL(p,0,1); /* level 1 */
  230.     SSVAL(p,2,0xFFFF - 500); /* buf length */
  231.     p += 4;
  232.     typep = (uint32 *)p;
  233.     p += 4;
  234.     strcpy(p,domain);
  235.     strupper(p);
  236.     p = skip_string(p,1);
  237.  
  238.     SIVAL(typep,0,0x80000000); /* domain list */
  239.  
  240.     if (call_remote_api(fd,cnum,uid,timeout,inbuf,outbuf,
  241.             PTR_DIFF(p,param),0,
  242.             8,0xFFFF - 500,
  243.             NULL,NULL,
  244.             param,NULL,
  245.             &rparam,&rdata) && SVAL(rparam,0)==0)
  246.     {
  247.       int converter=SVAL(rparam,2);
  248.       int count=SVAL(rparam,4);
  249.       int i;
  250.       char *p2 = rdata;
  251.       for (i=0;i<count;i++) {
  252.     char *sname = p2;
  253.     uint32 type = IVAL(p2,18);
  254.     int comment_offset = IVAL(p2,22) & 0xFFFF;
  255.     char *comment = comment_offset?(rdata+comment_offset-converter):"";
  256.  
  257.     add_server_entry(sname,type,lp_max_ttl(),comment,False);
  258.     p2 += 26;
  259.       }
  260.     }
  261.  
  262.     SIVAL(typep,0,0xFFFFFFFF); /* server list */
  263.  
  264.     if (call_remote_api(fd,cnum,uid,timeout,inbuf,outbuf,
  265.             PTR_DIFF(p,param),0,
  266.             8,0xFFFF - 500,
  267.             NULL,NULL,
  268.             param,NULL,
  269.             &rparam,&rdata) && SVAL(rparam,0)==0)
  270.     {
  271.       int converter=SVAL(rparam,2);
  272.       int count=SVAL(rparam,4);
  273.       int i;
  274.  
  275.       p = rdata;
  276.       for (i=0;i<count;i++) {
  277.     char *sname = p;
  278.     uint32 type = IVAL(p,18);
  279.     int comment_offset = IVAL(p,22) & 0xFFFF;
  280.     char *comment = comment_offset?(rdata+comment_offset-converter):"";
  281.  
  282.     add_server_entry(sname,type,lp_max_ttl(),comment,False);
  283.     p += 26;
  284.       }
  285.     }
  286.   }
  287.  
  288.   /* close up */
  289.   bzero(outbuf,smb_size);
  290.   set_message(outbuf,0,0,True);
  291.   CVAL(outbuf,smb_com) = SMBtdis;
  292.   SSVAL(outbuf,smb_uid,uid);
  293.   SSVAL(outbuf,smb_tid,cnum);
  294.   send_smb(fd,outbuf);
  295.   receive_smb(fd,inbuf,1000);
  296.   
  297.   close(fd);
  298.   if (inbuf) free(inbuf);
  299. }
  300.